package org.farng.mp3.lyrics3;

import org.farng.mp3.AbstractMP3Fragment;
import org.farng.mp3.InvalidTagException;
import org.farng.mp3.TagException;
import org.farng.mp3.TagOptionSingleton;
import org.farng.mp3.TagUtility;
import org.farng.mp3.id3.AbstractFrameBodyTextInformation;
import org.farng.mp3.id3.AbstractID3v2Frame;
import org.farng.mp3.id3.FrameBodyCOMM;
import org.farng.mp3.id3.FrameBodySYLT;
import org.farng.mp3.id3.FrameBodyUSLT;

import java.io.IOException;
import java.io.RandomAccessFile;


/**
 * Title:       Lyrics3v2Field Description: This class is an individual field
 * within a Lyrics3 tag Copyright:   Copyright (c) 2002 Company:
 *
 * @author Eric Farng
 * @version $Revision: 1.5 $
 */
public class Lyrics3v2Field extends AbstractMP3Fragment {
    /**
     * Creates a new Lyrics3v2Field object.
     */
    public Lyrics3v2Field() {}

    public Lyrics3v2Field(Lyrics3v2Field copyObject) {
        super(copyObject);
    }

    /**
     * Creates a new Lyrics3v2Field object.
     *
     * @param body DOCUMENT ME!
     */
    public Lyrics3v2Field(AbstractLyrics3v2FieldBody body) {
        this.body = body;
    }

    /**
     * Creates a new Lyrics3v2Field object.
     *
     * @param frame DOCUMENT ME!
     *
     * @throws TagException DOCUMENT ME!
     */
    public Lyrics3v2Field(AbstractID3v2Frame frame)
                   throws TagException {
        AbstractFrameBodyTextInformation textFrame;
        String                           text;
        String                           frameIdentifier = frame.getIdentifier();

        if (frameIdentifier.startsWith("USLT")) {
            body = new FieldBodyLYR("");
            ((FieldBodyLYR) body).addLyric((FrameBodyUSLT) frame.getBody());
        } else if (frameIdentifier.startsWith("SYLT")) {
            body = new FieldBodyLYR("");
            ((FieldBodyLYR) body).addLyric((FrameBodySYLT) frame.getBody());
        } else if (frameIdentifier.startsWith("COMM")) {
            text = new String(((FrameBodyCOMM) frame.getBody()).getText());
            body = new FieldBodyINF(text);
        } else if (frameIdentifier.equals("TCOM")) {
            textFrame = (AbstractFrameBodyTextInformation) frame.getBody();
            body      = new FieldBodyAUT("");

            if ((textFrame != null) && (((String) ((String) textFrame.getText())).length() > 0)) {
                body = new FieldBodyAUT(((String) textFrame.getText()));
            }
        } else if (frameIdentifier.equals("TALB")) {
            textFrame = (AbstractFrameBodyTextInformation) frame.getBody();

            if ((textFrame != null) && (((String) textFrame.getText()).length() > 0)) {
                body = new FieldBodyEAL(((String) textFrame.getText()));
            }
        } else if (frameIdentifier.equals("TPE1")) {
            textFrame = (AbstractFrameBodyTextInformation) frame.getBody();

            if ((textFrame != null) && (((String) textFrame.getText()).length() > 0)) {
                body = new FieldBodyEAR(((String) textFrame.getText()));
            }
        } else if (frameIdentifier.equals("TIT2")) {
            textFrame = (AbstractFrameBodyTextInformation) frame.getBody();

            if ((textFrame != null) && (((String) textFrame.getText()).length() > 0)) {
                body = new FieldBodyETT(((String) textFrame.getText()));
            }
        } else {
            throw new TagException("Cannot create Lyrics3v2 field from given ID3v2 frame");
        }
    }

    /**
     * Creates a new Lyrics3v2Field object.
     *
     * @param file DOCUMENT ME!
     *
     * @throws InvalidTagException DOCUMENT ME!
     * @throws IOException DOCUMENT ME!
     */
    public Lyrics3v2Field(RandomAccessFile file)
                   throws InvalidTagException, IOException {
        this.read(file);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String getIdentifier() {
        if (body == null) {
            return "";
        }

        return body.getIdentifier();
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public int getSize() {
        return body.getSize() + 5 + getIdentifier().length();
    }

    /**
     * DOCUMENT ME!
     *
     * @param file DOCUMENT ME!
     *
     * @throws InvalidTagException DOCUMENT ME!
     * @throws IOException DOCUMENT ME!
     */
    public void read(RandomAccessFile file)
              throws InvalidTagException, IOException {
        byte[] buffer = new byte[6];

        // lets scan for a non-zero byte;
        long filePointer;
        byte b;

        do {
            filePointer = file.getFilePointer();
            b           = file.readByte();
        } while (b == 0);

        file.seek(filePointer);

        // read the 3 character ID
        file.read(buffer, 0, 3);

        String identifier = new String(buffer, 0, 3);

        // is this a valid identifier?
        if (TagUtility.isLyrics3v2FieldIdentifier(identifier) == false) {
            throw new InvalidTagException(identifier + " is not a valid ID3v2.4 frame");
        }

        body = readBody(identifier, file);
    }

    /**
     * DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     */
    public String toString() {
        if (body == null) {
            return "";
        }

        return body.toString();
    }

    /**
     * DOCUMENT ME!
     *
     * @param file DOCUMENT ME!
     *
     * @throws IOException DOCUMENT ME!
     */
    public void write(RandomAccessFile file)
               throws IOException {
        if ((((AbstractLyrics3v2FieldBody) body).getSize() > 0) || TagOptionSingleton.getInstance().isLyrics3SaveEmptyField()) {
            byte[] buffer = new byte[3];

            String str = getIdentifier();

            for (int i = 0; i < str.length(); i++) {
                buffer[i] = (byte) str.charAt(i);
            }

            file.write(buffer, 0, str.length());

            body.write(file);
        }
    }

    /**
     * DOCUMENT ME!
     *
     * @param identifier DOCUMENT ME!
     * @param file DOCUMENT ME!
     *
     * @return DOCUMENT ME!
     *
     * @throws InvalidTagException DOCUMENT ME!
     * @throws IOException DOCUMENT ME!
     */
    private AbstractLyrics3v2FieldBody readBody(String identifier, RandomAccessFile file)
                                         throws InvalidTagException, IOException {
        AbstractLyrics3v2FieldBody newBody = null;

        if (identifier.equals("AUT")) {
            newBody = new FieldBodyAUT(file);
        } else if (identifier.equals("EAL")) {
            newBody = new FieldBodyEAL(file);
        } else if (identifier.equals("EAR")) {
            newBody = new FieldBodyEAR(file);
        } else if (identifier.equals("ETT")) {
            newBody = new FieldBodyETT(file);
        } else if (identifier.equals("IMG")) {
            newBody = new FieldBodyIMG(file);
        } else if (identifier.equals("IND")) {
            newBody = new FieldBodyIND(file);
        } else if (identifier.equals("INF")) {
            newBody = new FieldBodyINF(file);
        } else if (identifier.equals("LYR")) {
            newBody = new FieldBodyLYR(file);
        } else {
            newBody = new FieldBodyUnsupported(file);
        }

        return newBody;
    }
}